﻿
using Sys;

using System.Silverlight;
using System.Silverlight.Presentation;
using System.Silverlight.Presentation.Animation;
using System;
using seh = Sys.EventHandler;
using sea = Sys.EventArgs;
using va = SBT.VerticalAlignment;
using ha = SBT.HorizontalAlignment;

namespace SBT
{
    public enum HorizontalAlignment
    {
        Left = 1,
        Right = 2,
        Stretch = 3,
        Center = 4
    }
    public enum VerticalAlignment
    {
        Top = 1,
        Bottom = 2,
        Stretch = 3,
        Center = 4
    }
    public class Grid : AgLayoutManager
    {
        public static readonly string MarginLeft = "Grid.MarginLeft";
        public static readonly string MarginRight = "Grid.MarginRight";
        public static readonly string MarginTop = "Grid.MarginTop";
        public static readonly string MarginBottom = "Grid.MarginBottom";
        public static readonly string HorizontalAlignment = "Grid.HorizontalAlignment";
        public static readonly string VerticalAlignment = "Grid.VerticalAlignment";
        public static readonly string UpdatingLayout = "Grid.UpdatingLayout";
        private NamedValueChangedEventHandler m_childNamedValueChangedHandler;
        private seh m_childSizeChangedHandler;
        private seh m_sizeChangedHandler;
        
        protected override void OnUIElementAdded(UIElement item)
        {
            base.OnUIElementAdded(item);
            if (IsInitialized)
            {
                AgBehavior behavior = AgBehavior.FindBehaviorByUIElement(item);
                if (!(bool)(object)behavior)
                {
                    behavior = new AgBehavior();
                    behavior.Plugin = Plugin;
                    behavior.Element = item;
                    behavior.Initialize();
                }
                behavior.add_namedValueChanged(m_childNamedValueChangedHandler);
                behavior.add_widthChanged(m_childSizeChangedHandler);
                behavior.add_heightChanged(m_childSizeChangedHandler);
            }
        }
        protected override void OnUIElementRemoved(UIElement item)
        {
            base.OnUIElementRemoved(item);
            if (IsInitialized)
            {
                AgBehavior behavior = AgBehavior.FindBehaviorByUIElement(item);
                if (!(bool)(object)behavior)
                {
                    behavior = new AgBehavior();
                    behavior.Element = item;
                    behavior.Plugin = Plugin;
                    behavior.Initialize();
                }
                behavior.remove_namedValueChanged(m_childNamedValueChangedHandler);
                behavior.remove_widthChanged(m_childSizeChangedHandler);
                behavior.remove_heightChanged(m_childSizeChangedHandler);
            }
        }

        private void OnChildNamedValueChanged(object sender, NamedValueChangedEventArgs args)
        {
            if (args.Name == MarginBottom 
                || args.Name == MarginLeft
                || args.Name == MarginRight
                || args.Name == MarginTop
                || args.Name == HorizontalAlignment
                || args.Name == VerticalAlignment)
            {                
                    UpdateLayout((AgBehavior)sender);
            }
        }
        private void OnChildSizeChanged(object sender, sea args)
        {
            UpdateLayout((AgBehavior)sender);
        }
        public override void Initialize()
        {
            base.Initialize();
            m_childNamedValueChangedHandler = OnChildNamedValueChanged;
            m_childSizeChangedHandler = OnChildSizeChanged;
            m_sizeChangedHandler = OnSizeChanged;
            for (int i = 0; i < UnderlyingCanvas.Children.Count; i++)
            {
                UIElement item = UnderlyingCanvas.Children.GetItem(i);
                AgBehavior behavior = AgBehavior.FindBehaviorByUIElement(item);
                if (!(bool)(object)behavior)
                {
                    behavior = new AgBehavior();
                    behavior.Element = item;
                    behavior.Plugin = Plugin;
                    behavior.Initialize();
                }
                behavior.add_namedValueChanged(m_childNamedValueChangedHandler);
                behavior.add_widthChanged(m_childSizeChangedHandler);
                behavior.add_heightChanged(m_childSizeChangedHandler);
                this.add_widthChanged(m_sizeChangedHandler);
                this.add_heightChanged(m_sizeChangedHandler);
            }
        }
        private void OnSizeChanged(object sender, sea args)
        {
            if (IsInitialized)
                InvalidateLayout();
        }
        public override void InvalidateLayout()
        {
            if (!LayoutSuspended)
            {
                base.InvalidateLayout();
                for (int i = 0; i < UnderlyingCanvas.Children.Count; i++)
                {
                    UIElement item = UnderlyingCanvas.Children.GetItem(i);
                    AgBehavior behavior = AgBehavior.FindBehaviorByUIElement(item);
                    if (!(bool)(object)behavior)
                    {
                        behavior = new AgBehavior();
                        behavior.Element = item;
                        behavior.Plugin = Plugin;
                        behavior.Initialize();
                    }
                    UpdateLayout(behavior);
                }
            }
        }

        public void UpdateLayout(AgBehavior child)
        {
           
            if (!LayoutSuspended)
            {
                if (!(bool)child.GetNamedValue(UpdatingLayout))
                {
                    child.SetNamedValue(UpdatingLayout, true);
                    object oVerticalAlignment = child.GetNamedValue(VerticalAlignment);
                    object oHorizotalAlignment = child.GetNamedValue(HorizontalAlignment);
                    object oMarginLeft = child.GetNamedValue(MarginLeft);
                    object oMarginRight = child.GetNamedValue(MarginRight);
                    object oMarginTop = child.GetNamedValue(MarginTop);
                    object oMarginBottom = child.GetNamedValue(MarginBottom);
                    double marginLeft = 0;
                    double marginRight = 0;
                    double marginTop = 0;
                    double marginBottom = 0;
                    va vAlign = va.Stretch;
                    ha hAlign = ha.Stretch;
                    if ((bool)(object)oVerticalAlignment)
                    {
                        vAlign = (va)oVerticalAlignment;
                    }
                    if ((bool)(object)oHorizotalAlignment)
                    {
                        hAlign = (ha)oHorizotalAlignment;
                    }
                    if ((bool)(object)oMarginLeft)
                    {
                        marginLeft = (double)oMarginLeft;
                    }
                    if ((bool)(object)oMarginRight)
                    {
                        marginRight = (double)oMarginRight;
                    }
                    if ((bool)(object)oMarginTop)
                    {
                        marginTop = (double)oMarginTop;
                    }
                    if ((bool)(object)oMarginBottom)
                    {
                        marginBottom = (double)oMarginBottom;
                    }

                    // Horizontal :
                    switch (hAlign)
                    {
                        case ha.Stretch:
                            child.Left = marginLeft;
                            child.Width = Width - (marginLeft + marginRight);
                            break;
                        case ha.Center:
                            double horOffset = marginLeft - marginRight;
                            double left = ((Width - child.Width) / 2) + horOffset;
                            child.Left = left;
                            break;
                        case ha.Left:
                            child.Left = marginLeft;
                            break;
                        case ha.Right:
                            double left2 = Width - (child.Width + marginRight);
                            child.Left = left2;
                            break;
                    }

                    //Vertical :
                    switch (vAlign)
                    {
                        case va.Stretch:
                            child.Top = marginTop;
                            child.Height = Height - (marginTop + marginBottom);
                            break;
                        case va.Center:
                            double verOffset = marginTop - marginBottom;
                            double top = ((Height - child.Height) / 2) + verOffset;
                            child.Top = top;
                            break;
                        case va.Top:
                            child.Top = marginTop;
                            break;
                        case va.Bottom:
                            double top2 = Height - (child.Height + marginBottom);
                            child.Top = top2;
                            break;
                    }
                    child.SetNamedValue(UpdatingLayout, false);
                }
            }
        }
    }
}